package dao

import (
	"common/biz"
	"common/logs"
	"common/utils"
	"context"
	"core/models/db"
	"core/models/entity"
	"core/repo"
	"fmt"
	"framework/msError"
	game "game/models/request"
	gameFlee "game_flee/models/request"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"gorm.io/gorm"
	"hall/models/request"
	"strconv"
	"time"
)

type GameDao struct {
	repo *repo.Manager
}

// GameList 游戏列表
func (d *GameDao) GameList(ctx context.Context) *[]db.GameHasManyConf {
	data := new([]db.GameHasManyConf)
	d.repo.DB.Client.WithContext(ctx).Model(db.Game{}).Where("is_show=?", true).Preload("Conf").Find(data)
	return data
}

// GameUser 获取我的游戏账号信息
func (d *GameDao) GameUser(ctx context.Context, uid, gameID uint) *db.GameUserHasOneRolePoolOfSkill {
	data := new(db.GameUserHasOneRolePoolOfSkill)
	d.repo.DB.Client.WithContext(ctx).Model(db.GameUser{}).
		Preload("Role").
		Preload("Role.Skill").
		Where("game_id=? AND uid=?", gameID, uid).
		First(data)
	return data
}

// GetGameRolePool 获取角色池信息
func (d *GameDao) GetGameRolePool(ctx context.Context, gameID, roleID uint, isGifts bool) *db.GameRolePool {
	data := new(db.GameRolePool)
	whe := make(map[string]any)
	whe["game_id"] = gameID
	whe["is_gifts"] = isGifts
	if roleID != 0 {
		whe["id"] = roleID
	}
	d.repo.DB.Client.WithContext(ctx).Model(data).Where(whe).First(data)
	return data
}

// GameUserCreate 创建游戏角色
func (d *GameDao) GameUserCreate(ctx context.Context, user *db.GameUser, role *db.GameRole) *msError.Error {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	err := tx.Model(user).Create(user).Error
	if err != nil {
		logs.Error("[Game]用户%d Info GameUserCreate err:添加游戏用户失败 req=%v,dbErr=%v", user.UID, user, err)
		return biz.SqlError
	}
	err = tx.Model(role).Create(role).Error
	if err != nil {
		logs.Error("[Game]用户%d Info GameUserCreate err:赠送游戏角色失败 req=%v,dbErr=%v", user.UID, role, err)
		tx.Rollback()
		return biz.SqlError
	}
	tx.Commit()
	return nil
}

// GetCardInfo 获取卡牌信息
func (d *GameDao) GetCardInfo(ctx context.Context, typeId uint, types int) *db.GameCard {
	data := new(db.GameCard)
	whe := make(map[string]any)
	if typeId != 0 {
		whe["id"] = typeId
	}
	if types != 0 {
		whe["type"] = types
	}
	d.repo.DB.Client.WithContext(ctx).Model(data).Where(whe).First(data)
	return data
}

// GetConfVal 获取配置信息
func (d *GameDao) GetConfVal(ctx context.Context, gameID uint, name string) string {
	data := new(db.GameConf)
	d.repo.DB.Client.WithContext(ctx).Model(data).Where("game_id=? AND name=?", gameID, name).First(data)
	return data.Value
}

// GameRoles 获取我的所有角色信息
func (d *GameDao) GameRoles(ctx context.Context, uid uint, gameID uint) *[]db.GameRoleHasOneRolePoolOfSkill {
	data := new([]db.GameRoleHasOneRolePoolOfSkill)
	d.repo.DB.Client.WithContext(ctx).Model(db.GameRole{}).
		Preload("Pool").
		Preload("Pool.Skill").
		Where("game_id=? AND uid=?", gameID, uid).
		Find(data)
	return data
}

// GameRolePool 获取所有角色池信息
func (d *GameDao) GameRolePool(ctx context.Context, gameID uint) *[]db.GameRolePoolHasOneSkill {
	data := new([]db.GameRolePoolHasOneSkill)
	d.repo.DB.Client.WithContext(ctx).Model(db.GameRolePool{}).
		Preload("Skill").
		Preload("Types").
		Where("game_id=? ", gameID).
		Find(data)
	return data
}

// GetGameMyRole 获取我的角色信息
func (d *GameDao) GetGameMyRole(ctx context.Context, uid, gameID, roleID uint) *db.GameRole {
	data := new(db.GameRole)
	d.repo.DB.Client.WithContext(ctx).Model(data).Where("game_id=? AND uid=? AND role_id=?", gameID, uid, roleID).First(data)
	return data
}

// GameBuyRole 购买角色
func (d *GameDao) GameBuyRole(ctx context.Context, data *db.WarehouseMaterialHasOneType, pool *db.GameRolePool) *msError.Error {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	_mdb := d.repo.Mongo
	mtx, _ := _mdb.Client.StartSession()
	_ = mtx.StartTransaction()
	defer mtx.EndSession(ctx)
	//1.扣除游戏币
	warehouse := new(db.WarehouseMaterial)
	err := tx.Model(warehouse).Where("id=?", data.ID).Update("num", gorm.Expr("num-?", pool.Price)).Error
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:扣除材料失败 req=%v,dbErr=%v", data.UID, data, err)
		return biz.SqlError
	}
	// TODO 2.添加仓库材料记录
	material := &entity.MaterialLog{
		UID:        data.UID,
		WID:        data.ID,
		TypeID:     data.TypeID,
		TypeName:   data.Types.Name,
		TypeImg:    data.Types.Img,
		TypeModule: data.Types.Module,
		//LinkID:     order.OrderNo,
		LinkTable: "m_game_card_role_order",
		Ago:       data.Num,
		Num:       -pool.Price,
		After:     data.Num - pool.Price,
		Remarks:   "游戏-卡牌-购买角色",
		AddTime:   time.Now().Format(time.DateTime),
	}
	_, err = _mdb.Db.Collection("material_log").InsertOne(ctx, material)
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料变动记录失败 req=%v,dbErr=%v", data.UID, material, err)
		tx.Rollback()
		return biz.SqlError
	}
	//3.添加到我的角色池
	role := &db.GameRole{
		GameID: pool.GameID,
		UID:    data.UID,
		RoleID: pool.ID,
	}
	err = tx.Model(role).Create(role).Error
	//4.添加购买记录
	_, err = _mdb.Db.Collection("game_card_role_order").InsertOne(ctx, &entity.GameCardRoleOrder{
		GameID:     pool.GameID,
		UID:        data.UID,
		RoleID:     pool.ID,
		RoleName:   pool.Name,
		RoleImg:    pool.Img,
		RoleAvatar: pool.Avatar,
		TypeID:     data.TypeID,
		TypeName:   data.Types.Name,
		TypeImg:    data.Types.Img,
		TypeModule: data.Types.Module,
		Price:      pool.Price,
		PayTime:    time.Now().Format(time.DateTime),
	})
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料变动记录失败 req=%v,dbErr=%v", data.UID, material, err)
		tx.Rollback()
		_ = mtx.AbortTransaction(ctx)
		return biz.SqlError
	}
	_ = mtx.CommitTransaction(ctx)
	tx.Commit()
	return nil
}

// GameUseRole 使用角色
func (d *GameDao) GameUseRole(ctx context.Context, uid uint, req *request.GameCardRole) *msError.Error {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	//1.获取用户信息表
	user := d.GameUser(ctx, uid, req.ID)
	if user.RoleID == req.RoleID {
		return nil
	}
	//2.修改用户信息表角色信息
	err := tx.Model(db.GameUser{}).Where("game_id=? AND uid=?", req.ID, uid).Update("role_id", req.RoleID).Error
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:修改用户信息表角色信息失败 req=%v,dbErr=%v", uid, req, err)
		return biz.SqlError
	}
	//3.把用户池的所有角色改为未使用
	role := new(db.GameRole)
	err = tx.Model(role).Where("game_id=? AND uid=?", req.ID, uid).Update("is_use", false).Error
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:把用户池的所有角色改为未使用失败 req=%v,dbErr=%v", uid, req, err)
		tx.Rollback()
		return biz.SqlError
	}
	//3.把使用的角色改为使用状态
	err = tx.Model(role).Where("game_id=? AND uid=? AND role_id=?", req.ID, uid, req.RoleID).Update("is_use", true).Error
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:把使用的角色改为使用状态失败 req=%v,dbErr=%v", uid, req, err)
		tx.Rollback()
		return biz.SqlError
	}
	//4.添加角色变更记录
	_, err = d.repo.Mongo.Db.Collection("game_card_role_use").InsertOne(ctx, &entity.GameCardRoleUse{
		GameID:  req.ID,
		UID:     uid,
		RoleID:  req.RoleID,
		AddTime: time.Now().Format(time.DateTime),
	})
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加角色变更记录失败 req=%v,dbErr=%v", uid, req, err)
		tx.Rollback()
		return biz.SqlError
	}
	tx.Commit()
	return nil
}

// GameExchange 兑换
func (d *GameDao) GameExchange(ctx context.Context, log *entity.GameCardExchange, types *db.Type) *msError.Error {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	_mdb := d.repo.Mongo
	mtx, _ := _mdb.Client.StartSession()
	_ = mtx.StartTransaction()
	defer mtx.EndSession(ctx)
	var err error
	warehouse := new(db.WarehouseMaterial)
	var subMaterial, addMaterial entity.MaterialLog
	if log.Types == 1 {
		//1.扣除星金|星源
		_db.Model(warehouse).Where("uid=? AND type_id=?", log.UID, log.TypeID).First(warehouse)
		err = tx.Model(warehouse).Where("uid=? AND type_id=?", log.UID, log.TypeID).Update("num", gorm.Expr("num-?", log.Count)).Error
		if err != nil {
			logs.Error("[Game]用户%d BuyRole GameBuyRole err:扣除材料失败 req=%v,dbErr=%v", log.UID, log, err)
			return biz.SqlError
		}
		subMaterial = entity.MaterialLog{
			UID:        log.UID,
			WID:        warehouse.ID,
			TypeID:     log.TypeID,
			TypeName:   log.TypeName,
			TypeImg:    log.TypeImg,
			TypeModule: log.TypeModule,
			//LinkID:     order.OrderNo,
			LinkTable: "m_game_card_exchange_log",
			Ago:       warehouse.Num,
			Num:       -log.Count,
			After:     warehouse.Num - log.Count,
			Remarks:   fmt.Sprintf("游戏-兑换%v", types.Name),
			AddTime:   time.Now().Format(time.DateTime),
		}
		//2.添加游戏币
		warehouse = new(db.WarehouseMaterial)
		_db.Model(warehouse).Where("uid=? AND type_id=?", log.UID, types.ID).First(warehouse)
		err = tx.Model(warehouse).Where("uid=? AND type_id=?", log.UID, types.ID).Update("num", gorm.Expr("num+?", log.Num)).Error
		if err != nil {
			logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料失败 req=%v,dbErr=%v", log.UID, log, err)
			return biz.SqlError
		}
		addMaterial = entity.MaterialLog{
			UID:        log.UID,
			WID:        warehouse.ID,
			TypeID:     types.ID,
			TypeName:   types.Name,
			TypeImg:    types.Img,
			TypeModule: types.Module,
			//LinkID:     order.OrderNo,
			LinkTable: "m_game_card_exchange_log",
			Ago:       warehouse.Num,
			Num:       log.Num,
			After:     warehouse.Num + log.Num,
			Remarks:   fmt.Sprintf("游戏-%v兑换", log.TypeName),
			AddTime:   time.Now().Format(time.DateTime),
		}
	} else {
		//1.扣除游戏币
		_db.Model(warehouse).Where("uid=? AND type_id=?", log.UID, types.ID).First(warehouse)
		err = tx.Model(warehouse).Where("uid=? AND type_id=?", log.UID, types.ID).Update("num", gorm.Expr("num+?", log.Num)).Error
		if err != nil {
			logs.Error("[Game]用户%d BuyRole GameBuyRole err:扣除材料失败 req=%v,dbErr=%v", log.UID, log, err)
			return biz.SqlError
		}
		subMaterial = entity.MaterialLog{
			UID:        log.UID,
			WID:        warehouse.ID,
			TypeID:     types.ID,
			TypeName:   types.Name,
			TypeImg:    types.Img,
			TypeModule: types.Module,
			//LinkID:     order.OrderNo,
			LinkTable: "m_game_card_exchange_log",
			Ago:       warehouse.Num,
			Num:       log.Num,
			After:     warehouse.Num + log.Num,
			Remarks:   fmt.Sprintf("游戏-兑换%v", log.TypeName),
			AddTime:   time.Now().Format(time.DateTime),
		}
		//2.添加星金|星源
		warehouse = new(db.WarehouseMaterial)
		_db.Model(warehouse).Where("uid=? AND type_id=?", log.UID, log.TypeID).First(warehouse)
		err = tx.Model(warehouse).Where("uid=? AND type_id=?", log.UID, log.TypeID).Update("num", gorm.Expr("num+?", log.Count)).Error
		if err != nil {
			logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料失败 req=%v,dbErr=%v", log.UID, log, err)
			return biz.SqlError
		}
		addMaterial = entity.MaterialLog{
			UID:        log.UID,
			WID:        warehouse.ID,
			TypeID:     log.TypeID,
			TypeName:   log.TypeName,
			TypeImg:    log.TypeImg,
			TypeModule: log.TypeModule,
			//LinkID:     order.OrderNo,
			LinkTable: "m_game_card_exchange_log",
			Ago:       warehouse.Num,
			Num:       log.Count,
			After:     warehouse.Num + log.Count,
			Remarks:   fmt.Sprintf("游戏-%v兑换", types.Name),
			AddTime:   time.Now().Format(time.DateTime),
		}
	}
	// TODO 3.添加材料变动记录-扣除
	_, err = _mdb.Db.Collection("material_log").InsertOne(ctx, subMaterial)
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料变动记录失败 req=%v,dbErr=%v", log.UID, subMaterial, err)
		tx.Rollback()
		return biz.SqlError
	}
	// TODO 4.添加材料变动记录-添加
	_, err = _mdb.Db.Collection("material_log").InsertOne(ctx, addMaterial)
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料变动记录失败 req=%v,dbErr=%v", log.UID, addMaterial, err)
		tx.Rollback()
		_ = mtx.AbortTransaction(ctx)
		return biz.SqlError
	}
	//5.添加兑换记录
	_, err = _mdb.Db.Collection("game_card_exchange_log").InsertOne(ctx, log)
	if err != nil {
		logs.Error("[Game]用户%d BuyRole GameBuyRole err:添加材料变动记录失败 req=%v,dbErr=%v", log.UID, addMaterial, err)
		tx.Rollback()
		_ = mtx.AbortTransaction(ctx)
		return biz.SqlError
	}
	_ = mtx.CommitTransaction(ctx)
	tx.Commit()
	return nil
}

func (d *GameDao) GetConf(ctx context.Context, gameID uint) *[]db.GameConf {
	data := new([]db.GameConf)
	d.repo.DB.Client.WithContext(ctx).Model(db.GameConf{}).
		Where("game_id=? ", gameID).
		Find(data)
	return data
}
func (d *GameDao) GetConfInfo(ctx context.Context, gameID uint, name string) *db.GameConf {
	data := new(db.GameConf)
	d.repo.DB.Client.WithContext(ctx).Model(data).
		Where("game_id=? AND name=?", gameID, name).
		First(data)
	return data
}

// GetGameCard 全部卡牌
func (d *GameDao) GetGameCard(ctx context.Context, gameID uint) *[]db.GameCard {
	data := new([]db.GameCard)
	d.repo.DB.Client.WithContext(ctx).Model(db.GameCard{}).
		Where("game_id=? AND is_show=?", gameID, true).
		Find(data)
	return data
}

func (d *GameDao) FleeBetting(ctx context.Context, roomID, myRoomID uint, roomName string, uid uint, rounds, num int64, robot bool) (int64, *msError.Error) {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	_mdb := d.repo.Mongo
	var err error
	//1.扣除用户下注数量
	material := new(db.WarehouseMaterial)
	materialType := new(db.WarehouseMaterialHasOneType)
	_db.Model(material).Where("uid=? AND type_id=?", uid, 12).Preload("Types").First(materialType)
	if materialType.Num < num {
		logs.Error("[Game]用户%d FleeBetting err:用户%d 扣除用户下注数量失败 req=%v,dbErr=%v", uid, uid, num, err)
		return 0, biz.GameCurrencyError
	}
	err = tx.Model(material).Where("id=?", materialType.ID).Update("num", gorm.Expr("num-?", num)).Error
	if err != nil {
		logs.Error("[Game]用户%d FleeBetting err:用户%d 扣除用户下注数量失败 req=%v,dbErr=%v", uid, uid, num, err)
		return 0, biz.SqlError
	}
	//添加材料变动记录
	materialLog := entity.MaterialLog{
		UID:        uid,
		WID:        materialType.ID,
		TypeID:     materialType.TypeID,
		TypeName:   materialType.Types.Name,
		TypeImg:    materialType.Types.Img,
		TypeModule: materialType.Types.Module,
		LinkID:     "",
		LinkTable:  "m_game_flee_room_betting_log",
		Ago:        materialType.Num,
		Num:        -num,
		After:      materialType.Num - num,
		Remarks:    fmt.Sprintf("游戏-七号基地-第%d回合-下注%d", rounds, num),
		AddTime:    time.Now().Format(time.DateTime),
	}
	_, err = _mdb.Db.Collection("material_log").InsertOne(ctx, materialLog)
	if err != nil {
		logs.Error("[Game]用户%d FleeBetting err:添加材料变动记录失败 req=%v,dbErr=%v", uid, materialLog, err)
		tx.Rollback()
		return 0, biz.SqlError
	}
	//2.添加用户下注记录
	//查询是否已下注
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	collection := _mdb.Db.Collection("game_flee_room_betting_log")

	singleResult := collection.FindOne(ctx, bson.D{
		{"uid", uid},
		{"roomID", myRoomID},
		{"rounds", rounds},
		{"status", 0},
		{"dates", dates},
	})
	betting := new(entity.GameFleeRoomBetting)
	_ = singleResult.Decode(betting)
	var count int64
	if betting.UID == 0 {
		//添加
		betting = &entity.GameFleeRoomBetting{
			UID:        uid,
			RoomID:     roomID,
			RoomName:   roomName,
			Rounds:     rounds,
			TypeID:     materialType.TypeID,
			TypeName:   materialType.Types.Name,
			TypeImg:    materialType.Types.Img,
			TypeModule: materialType.Types.Module,
			Num:        num,
			Reward:     0,
			Status:     0,
			IsRobot:    robot,
			Dates:      dates,
			AddTime:    time.Now().Format(time.DateTime),
		}
		_, err = collection.InsertOne(ctx, betting)
	} else {
		//修改
		_, err = collection.UpdateOne(ctx, bson.D{
			{"_id", betting.Id},
		}, bson.M{
			"$set": bson.M{
				"roomID":   roomID,
				"roomName": roomName,
			},
			"$inc": bson.M{
				"num": num,
			},
		})
		count++
	}
	if err != nil {
		logs.Error("[Game]用户%d FleeBetting err:添加用户下注记录失败 req=%v,dbErr=%v", uid, betting, err)
		tx.Rollback()
		return 0, biz.SqlError
	}
	//if robot {
	//	//人机修改为已使用
	//	role := new(db.Role)
	//	_db.Model(role).Where("uid=?", uid).Update("is_use", true)
	//}
	tx.Commit()
	return count, nil
}

// FleeChangeRoom 更换房间
func (d *GameDao) FleeChangeRoom(ctx context.Context, roomID, myRoomID uint, roomName string, uid uint, rounds int64) *msError.Error {
	_mdb := d.repo.Mongo
	var err error
	//查询是否已下注
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	collection := _mdb.Db.Collection("game_flee_room_betting_log")
	singleResult := collection.FindOne(ctx, bson.D{
		{"uid", uid},
		{"roomID", myRoomID},
		{"rounds", rounds},
		{"status", 0},
		{"dates", dates},
	})
	betting := new(entity.GameFleeRoomBetting)
	_ = singleResult.Decode(betting)
	if betting.UID == 0 {
		return biz.GameNotBettingChangeRoomError
	}
	//修改
	_, err = collection.UpdateOne(ctx, bson.D{
		{"_id", betting.Id},
	}, bson.M{
		"$set": bson.M{
			"roomID":   roomID,
			"roomName": roomName,
		},
	})
	if err != nil {
		logs.Error("[Game]用户%d FleeChangeRoom err:修改用户下注记录失败 req=%v,dbErr=%v", uid, betting, err)
		return biz.SqlError
	}
	return nil
}

func (d *GameDao) KillRoom(ctx context.Context, rounds int64, roomID uint, roomName string) (*entity.GameFleeKillRoom, error) {
	var err error
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	bettingLog := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	whe := bson.D{
		{"roomID", roomID},
		{"rounds", rounds},
		{"status", 0},
		{"dates", dates},
	}
	aggregate, _ := bettingLog.Aggregate(ctx, mongo.Pipeline{bson.D{
		{"$match", whe},
	}, bson.D{
		{"$group", bson.D{
			{"_id", nil},
			{"total", bson.D{
				{"$sum", "$num"},
			}},
		}},
	}})
	var showsWithInfo []map[string]interface{}
	_ = aggregate.All(context.TODO(), &showsWithInfo)
	var killNum int64
	if len(showsWithInfo) > 0 {
		killNum = showsWithInfo[0]["total"].(int64)
	}
	count, _ := bettingLog.CountDocuments(ctx, whe)
	//修改被杀死状态
	_, err = bettingLog.UpdateMany(ctx, whe, bson.M{
		"$set": bson.M{
			"isKill": true,
		},
	})
	if err != nil {
		err = fmt.Errorf("[Game]用户%d KillRoom err:修改用户下注记录失败 req=%v,dbErr=%v", roomID, bettingLog, err)
		return nil, err
	}
	//添加房间被杀记录
	killLog := d.repo.Mongo.Db.Collection("game_flee_room_kill_log")
	log := entity.GameFleeKillRoom{
		RoomID:    roomID,
		RoomName:  roomName,
		Rounds:    rounds,
		KillNum:   killNum,
		KillCount: count,
		KillTime:  dates,
		AddTime:   time.Now().Format(time.DateTime),
	}
	_, err = killLog.InsertOne(ctx, log)
	if err != nil {
		err = fmt.Errorf("[Game]用户%d KillRoom err:添加用户下注记录失败 req=%v,dbErr=%v", roomID, log, err)
		return nil, err
	}
	return &log, nil
}

func (d *GameDao) EndGameCard(ctx context.Context, users *[]game.EndGameUsers, roomID string, total int64, peopleNum int, champion float64, runner float64, place float64) error {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	_mdb := d.repo.Mongo
	mtx, _ := _mdb.Client.StartSession()
	_ = mtx.StartTransaction()
	defer mtx.EndSession(ctx)
	var err error

	rewardMax := d.GetConfInfo(ctx, 0, "rand_reward_max")
	rewardMaxInt, _ := strconv.Atoi(rewardMax.Value)
	rewardMaxInt *= 100
	syTotal := utils.DecimalIntByFloat(total)
	var feeStr string
	_db.Model(&db.GameConf{}).Where("game_id=0 and name=?", "fee").Select("value").Scan(&feeStr)
	fee, _ := strconv.ParseFloat(feeStr, 64)
	syTotal = utils.DecimalFloatSub(syTotal, utils.DecimalFloatMul(syTotal, fee))

	materialLogM := _mdb.Db.Collection("material_log")
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	gameCardLogMongo := _mdb.Db.Collection("game_card_log")

	//计算积分
	var average = total / int64(peopleNum)
	integralTypes := new(db.Type)
	_db.Model(integralTypes).Where("id=?", 13).First(integralTypes)
	var integral = average / 100
	//计算碎片
	var debris int64 = 1
	var debrisTypeIDs = []uint{22, 23, 24, 25, 26}
	var maxDebrisLevel int
	if integral == 10 {
		maxDebrisLevel = 2
	} else if integral == 50 {
		maxDebrisLevel = 4
	}

	for _, v := range *users {
		gameCardLog := new(entity.GameCardLog)
		gameCardLogFind := gameCardLogMongo.FindOne(ctx, bson.D{
			{"roomID", roomID},
			{"uid", v.UID},
		})
		err = gameCardLogFind.Decode(gameCardLog)
		if err != nil {
			logs.Error("房间%v，用户%d没找到数据-----------", roomID, v.UID)
			continue
		}
		gameCardLog.Ranking = v.Ranking
		gameCardLog.Blood = v.Blood
		gameCardLog.Level = v.Level
		gameCardLog.ChairID = v.ChairID
		gameCardLog.IsSkill = v.IsSkill
		gameCardLog.SkillType = v.SkillType
		//gameCardLog.HandCards = v.HandCards
		//gameCardLog.SiteCards = v.SiteCards
		//gameCardLog.Battle = v.Battle
		gameCardLog.IsHangUp = v.IsHangUp
		gameCardLog.Status = true
		gameCardLog.Dates = dates
		gameCardLog.IsEnd = true
		if !v.IsHangUp {
			//发放积分
			material := new(db.WarehouseMaterial)
			_db.Model(material).Where("uid=? and type_id=?", v.UID, integralTypes.ID).First(material)
			var ago, after int64
			if material == nil || material.ID == 0 {
				material = &db.WarehouseMaterial{
					UID:    v.UID,
					TypeID: integralTypes.ID,
					Num:    integral,
				}
				err = tx.Model(material).Create(material).Error
				ago = 0
				after = material.Num
			} else {
				ago = material.Num
				after = material.Num + integral
				err = tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", integral)).Error
			}
			if err != nil {
				err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料失败 req=%v,dbErr=%v", v.UID, material, err)
				break
			}
			materialLog := &entity.MaterialLog{
				UID:        v.UID,
				WID:        material.ID,
				TypeID:     material.TypeID,
				TypeName:   integralTypes.Name,
				TypeImg:    integralTypes.Img,
				TypeModule: integralTypes.Module,
				LinkID:     roomID,
				LinkTable:  "m_game_card_log",
				Ago:        ago,
				Num:        integral,
				After:      after,
				Remarks:    "游戏-卡牌奖励",
				AddTime:    time.Now().Format(time.DateTime),
			}
			_, err = materialLogM.InsertOne(ctx, materialLog)
			if err != nil {
				err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料日志失败 req=%v,dbErr=%v", v.UID, materialLog, err)
				break
			}
			gameCardLog.IntegralTypeID = material.TypeID
			gameCardLog.IntegralTypeName = integralTypes.Name
			gameCardLog.IntegralTypeImg = integralTypes.Img
			gameCardLog.Integral = integral
			//碎片
			rands := utils.Random(1, 100) //获取一个随机值
			gameCardLog.Rands = rands
			if rands <= int64(rewardMaxInt) {
				//奖励碎片
				var debrisTypeIDRands int64 //随机获取碎片类型
				if maxDebrisLevel != 0 {
					debrisTypeIDRands = utils.Random(0, maxDebrisLevel)
				}
				debrisTypeID := debrisTypeIDs[int(debrisTypeIDRands)] //获取碎片类型
				debrisTypes := new(db.Type)
				_db.Model(debrisTypes).Where("id=?", debrisTypeID).First(debrisTypes)
				material = new(db.WarehouseMaterial)
				_db.Model(material).Where("uid=? and type_id=?", v.UID, debrisTypes.ID).First(material)
				if material == nil || material.ID == 0 {
					material = &db.WarehouseMaterial{
						UID:    v.UID,
						TypeID: debrisTypes.ID,
						Num:    debris,
					}
					err = tx.Model(material).Create(material).Error
					ago = 0
					after = material.Num
				} else {
					ago = material.Num
					after = material.Num + debris
					err = tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", debris)).Error
				}
				if err != nil {
					err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料失败 req=%v,dbErr=%v", v.UID, material, err)
					break
				}
				materialLog = &entity.MaterialLog{
					UID:        v.UID,
					WID:        material.ID,
					TypeID:     material.TypeID,
					TypeName:   debrisTypes.Name,
					TypeImg:    debrisTypes.Img,
					TypeModule: debrisTypes.Module,
					LinkID:     roomID,
					LinkTable:  "m_game_card_log",
					Ago:        ago,
					Num:        debris,
					After:      after,
					Remarks:    "游戏-卡牌奖励",
					AddTime:    time.Now().Format(time.DateTime),
				}
				_, err = materialLogM.InsertOne(ctx, materialLog)
				if err != nil {
					err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料日志失败 req=%v,dbErr=%v", v.UID, materialLog, err)
					break
				}
				gameCardLog.DebrisTypeID = debrisTypes.ID
				gameCardLog.DebrisTypeName = debrisTypes.Name
				gameCardLog.DebrisTypeImg = debrisTypes.Img
				gameCardLog.Debris = debris
			}
			types := new(db.Type)
			_db.Model(types).Where("id=?", 12).First(types)
			if gameCardLog.Ranking == 1 {
				gameCardLog.RewardTypeID = types.ID
				gameCardLog.RewardTypeName = types.Name
				gameCardLog.RewardTypeImg = types.Img
				gameCardLog.RewardNum = utils.DecimalFloatByInt(utils.DecimalFloatMul(syTotal, champion))
			} else if gameCardLog.Ranking == 2 {
				gameCardLog.RewardTypeID = types.ID
				gameCardLog.RewardTypeName = types.Name
				gameCardLog.RewardTypeImg = types.Img
				gameCardLog.RewardNum = utils.DecimalFloatByInt(utils.DecimalFloatMul(syTotal, runner))
			} else if gameCardLog.Ranking == 3 {
				gameCardLog.RewardTypeID = types.ID
				gameCardLog.RewardTypeName = types.Name
				gameCardLog.RewardTypeImg = types.Img
				gameCardLog.RewardNum = utils.DecimalFloatByInt(utils.DecimalFloatMul(syTotal, place))
			}
			if gameCardLog.RewardTypeID != 0 {
				rankingStr := []string{
					0: "无",
					1: "冠军",
					2: "亚军",
					3: "季军",
				}
				material = new(db.WarehouseMaterial)
				_db.Model(material).Where("uid=? and type_id=?", v.UID, gameCardLog.RewardTypeID).First(material)
				if material == nil || material.ID == 0 {
					//添加数据
					material = &db.WarehouseMaterial{
						UID:    v.UID,
						TypeID: gameCardLog.RewardTypeID,
						Num:    gameCardLog.RewardNum,
					}
					err = tx.Model(material).Create(material).Error
					ago = 0
					after = material.Num
				} else {
					//inc数据
					ago = material.Num
					after = material.Num + gameCardLog.RewardNum
					err = tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", gameCardLog.RewardNum)).Error
				}
				if err != nil {
					err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料失败 req=%v,dbErr=%v", v.UID, material, err)
					break
				}
				materialLog = &entity.MaterialLog{
					UID:        v.UID,
					WID:        material.ID,
					TypeID:     gameCardLog.RewardTypeID,
					TypeName:   types.Name,
					TypeImg:    types.Img,
					TypeModule: types.Module,
					LinkID:     roomID,
					LinkTable:  "m_game_card_log",
					Ago:        ago,
					Num:        gameCardLog.RewardNum,
					After:      after,
					Remarks:    fmt.Sprintf("游戏-卡牌-%v奖励", rankingStr[gameCardLog.Ranking]),
					AddTime:    time.Now().Format(time.DateTime),
				}
				_, err = materialLogM.InsertOne(ctx, materialLog)
				if err != nil {
					err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料日志失败 req=%v,dbErr=%v", v.UID, materialLog, err)
					break
				}
			}
		}
		//_, err = gameCardLogMongo.InsertOne(ctx, gameCardLog)
		_, err = gameCardLogMongo.UpdateOne(ctx, bson.M{"_id": gameCardLog.Id}, bson.M{"$set": gameCardLog})
		if err != nil {
			err = fmt.Errorf("[Game]用户%d EndGameCard err:添加游戏记录失败 req=%v,dbErr=%v", v.UID, gameCardLog, err)
			break
		}
	}
	if err != nil {
		tx.Rollback()
		_ = mtx.AbortTransaction(ctx)
		return err
	}
	_ = mtx.CommitTransaction(ctx)
	tx.Commit()
	return nil
}

func (d *GameDao) EndGameCardOne(ctx context.Context, uid uint, roomID string) error {
	_mdb := d.repo.Mongo
	_, err := _mdb.Db.Collection("game_card_log").UpdateOne(ctx, bson.D{
		{"uid", uid},
		{"roomID", roomID},
	}, bson.M{"$set": bson.M{"isEnd": true}})
	return err
}

func (d *GameDao) GameFleeUsers(ctx context.Context, rounds int64) *[]entity.GameFleeRoomBetting {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	//获取当前回合的用户数组
	cur, err := d.repo.Mongo.Db.Collection("game_flee_room_betting_log").Find(ctx, bson.D{
		{"rounds", rounds},
		{"dates", dates},
		{"status", 0},
	})
	var users []entity.GameFleeRoomBetting
	for cur.Next(ctx) {
		var result entity.GameFleeRoomBetting
		err = cur.Decode(&result)
		if err == mongo.ErrNoDocuments {
			return nil
		}
		users = append(users, result)
	}
	return &users
}

func (d *GameDao) GameFleeKillTotal(ctx context.Context, rounds int64) int64 {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	killLog := d.repo.Mongo.Db.Collection("game_flee_room_kill_log")
	aggregate, _ := killLog.Aggregate(ctx, mongo.Pipeline{bson.D{
		{"$match", bson.D{
			{"rounds", rounds},
			{"killTime", dates},
		}},
	}, bson.D{
		{"$group", bson.D{
			{"_id", nil},
			{"total", bson.D{
				{"$sum", "$killNum"},
			}},
		}},
	}})
	var showsWithInfo []map[string]interface{}
	_ = aggregate.All(context.TODO(), &showsWithInfo)
	//总杀死房间的游戏币数
	var killNum int64
	if len(showsWithInfo) > 0 {
		killNum = showsWithInfo[0]["total"].(int64)
	}
	return killNum
}
func (d *GameDao) GameFleeWinTotal(ctx context.Context, rounds int64) int64 {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	bettingLog := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	aggregate, _ := bettingLog.Aggregate(ctx, mongo.Pipeline{bson.D{
		{"$match", bson.D{
			{"rounds", rounds},
			{"dates", dates},
			{"isKill", false},
			{"status", 0},
		}},
	}, bson.D{
		{"$group", bson.D{
			{"_id", nil},
			{"total", bson.D{
				{"$sum", "$num"},
			}},
		}},
	}})
	var showsWithInfo []map[string]interface{}
	_ = aggregate.All(context.TODO(), &showsWithInfo)
	//总杀死房间的游戏币数
	var winNum int64
	if len(showsWithInfo) > 0 {
		winNum = showsWithInfo[0]["total"].(int64)
	}
	return winNum
}
func (d *GameDao) GameFleeWinCount(ctx context.Context, rounds int64) int64 {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	bettingLog := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	count, _ := bettingLog.CountDocuments(ctx, bson.D{
		{"rounds", rounds},
		{"dates", dates},
		{"isKill", false},
		{"status", 0},
	})
	return count
}

func (d *GameDao) EndGameFlee(ctx context.Context, rounds int64, users *[]entity.GameFleeRoomBetting, winCount, winTotal, killNum int64) (*[]entity.GameFleeRoomBetting, error) {
	_db := d.repo.DB.Client.WithContext(ctx)
	tx := _db.Begin()
	_mdb := d.repo.Mongo
	mtx, _ := _mdb.Client.StartSession()
	_ = mtx.StartTransaction()
	defer mtx.EndSession(ctx)
	var err error
	//dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	rewardMax := d.GetConfInfo(ctx, 0, "rand_reward_max")
	rewardMaxInt, _ := strconv.Atoi(rewardMax.Value)
	if rewardMaxInt == 0 {
		rewardMaxInt = 100
	}
	materialLogM := _mdb.Db.Collection("material_log")
	types := new(db.Type)
	_db.Model(types).Where("id=?", 12).First(types)
	//退还下注金额
	userData := *users
	//var declineId primitive.ObjectID
	//var declineUid uint
	//var declineKey int
	//var declineNum int64
	for k, v := range userData {
		// TODO 大逃杀随机奖励
		v.Status = 1
		//退还金额
		material := new(db.WarehouseMaterial)
		_db.Model(material).Where("uid=? and type_id=?", v.UID, types.ID).First(material)
		if !v.IsKill {
			var ago, after int64
			if material == nil || material.ID == 0 {
				//添加数据
				material = &db.WarehouseMaterial{
					UID:    v.UID,
					TypeID: types.ID,
					Num:    v.Num,
				}
				err = tx.Model(material).Create(material).Error
				ago = 0
				after = material.Num
			} else {
				//inc数据
				ago = material.Num
				after = material.Num + v.Num
				err = tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", v.Num)).Error
			}
			if err != nil {
				err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料失败 req=%v,dbErr=%v", v.UID, material, err)
				break
			}
			materialLog := &entity.MaterialLog{
				UID:        v.UID,
				WID:        material.ID,
				TypeID:     material.TypeID,
				TypeName:   types.Name,
				TypeImg:    types.Img,
				TypeModule: types.Module,
				LinkID:     fmt.Sprintf("%d", rounds),
				LinkTable:  "m_game_flee_room_betting_log",
				Ago:        ago,
				Num:        v.Num,
				After:      after,
				Remarks:    "游戏-七号基地-胜利 退回",
				AddTime:    time.Now().Format(time.DateTime),
			}
			_, err = materialLogM.InsertOne(ctx, materialLog)
			if err != nil {
				err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料日志失败 req=%v,dbErr=%v", v.UID, materialLog, err)
				break
			}
			v.ReturnNum = v.Num
		}
		//else {
		//	if v.Num > declineNum {
		//		declineId = v.Id
		//		declineUid = v.UID
		//		declineNum = v.Num
		//		declineKey = k
		//	}
		//}
		//修改记录
		_, err = _mdb.Db.Collection("game_flee_room_betting_log").UpdateOne(ctx, bson.D{
			{"_id", v.Id},
		}, bson.M{"$set": bson.D{
			{"returnNum", v.ReturnNum},
			{"rands", v.Rands},
			{"status", v.Status},
			{"randsReward", v.RandsReward},
		}})
		if err != nil {
			err = fmt.Errorf("[Game]用户%d EndGameCard err:修改下注记录失败 req=%v,dbErr=%v", v.UID, material, err)
			break
		}
		if v.IsRobot {
			role := new(db.Role)
			_db.Model(role).Where("uid=?", v.UID).Update("is_use", false)
		}
		userData[k] = v
	}
	if err != nil {
		tx.Rollback()
		_ = mtx.AbortTransaction(ctx)
		return nil, err
	}
	//给衰神加buf
	//if declineUid != 0 {
	//	_, err = _mdb.Db.Collection("game_flee_room_betting_log").UpdateOne(ctx, bson.D{
	//		{"_id", declineId},
	//		//{"uid", declineUid},
	//		//{"rounds", rounds},
	//		//{"dates", dates},
	//		//{"status", 1},
	//	}, bson.M{"$set": bson.D{
	//		{"isDecline", true},
	//	}})
	//	if err != nil {
	//		err = fmt.Errorf("[Game]用户%d EndGameCard err:修改下注记录失败 dbErr=%v", declineUid, err)
	//		tx.Rollback()
	//		_ = mtx.AbortTransaction(ctx)
	//		return nil, err
	//	}
	//	userData[declineKey].IsDecline = true
	//}
	if killNum <= 0 {
		_ = mtx.CommitTransaction(ctx)
		tx.Commit()
		return &userData, nil
	}
	//官方手续费
	//var feeInt, maxKillNum int64
	var feeInt int64
	info := d.GetConfInfo(ctx, 0, "fee")
	fee, _ := strconv.ParseFloat(info.Value, 64)
	feeInt = utils.DecimalFloatByInt(utils.DecimalFloatMul(utils.DecimalIntByFloat(killNum), fee))
	//剩余数量
	killTotal := killNum - feeInt
	//if rounds > 1 {
	//	//上回合输的最多的人奖励
	//	user := d.FleeMaxKillUser(ctx, rounds-1, dates)
	//	if user != nil && user.UID != 0 {
	//		info = d.GetConfInfo(ctx, 2, "special_rewards")
	//		specialRewards, _ := strconv.ParseFloat(info.Value, 64)
	//		maxKillNum = utils.DecimalFloatByInt(utils.DecimalFloatMul(utils.DecimalIntByFloat(killNum), specialRewards))
	//		killTotal -= maxKillNum
	//		material := new(db.WarehouseMaterial)
	//		_db.Model(material).Where("uid=? and type_id=?", user.UID, types.ID).First(material)
	//		if material != nil && material.ID != 0 {
	//			err = tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", maxKillNum)).Error
	//			if err != nil {
	//				err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料失败 req=%v,dbErr=%v", user.UID, material, err)
	//				tx.Rollback()
	//				_ = mtx.AbortTransaction(ctx)
	//				return nil, err
	//			}
	//			materialLog := &entity.MaterialLog{
	//				UID:        user.UID,
	//				WID:        material.ID,
	//				TypeID:     material.TypeID,
	//				TypeName:   types.Name,
	//				TypeImg:    types.Img,
	//				TypeModule: types.Module,
	//				LinkID:     fmt.Sprintf("%d", rounds),
	//				LinkTable:  "m_game_flee_room_betting_log",
	//				Ago:        material.Num,
	//				Num:        maxKillNum,
	//				After:      material.Num + maxKillNum,
	//				Remarks:    "游戏-七号基地-海神的馈赠",
	//				AddTime:    time.Now().Format(time.DateTime),
	//			}
	//			_, err = materialLogM.InsertOne(ctx, materialLog)
	//			if err != nil {
	//				err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料日志失败 req=%v,dbErr=%v", user.UID, materialLog, err)
	//				tx.Rollback()
	//				_ = mtx.AbortTransaction(ctx)
	//				return nil, err
	//			}
	//		}
	//		_, err = _mdb.Db.Collection("game_flee_room_betting_log").UpdateOne(ctx, bson.D{
	//			{"_id", user.Id},
	//		}, bson.M{"$set": bson.D{
	//			{"declineRewardTypeID", material.TypeID},
	//			{"declineRewardTypeName", types.Name},
	//			{"declineRewardTypeImg", types.Img},
	//			{"declineReward", maxKillNum},
	//		}})
	//		if err != nil {
	//			err = fmt.Errorf("[Game]用户%d EndGameCard err:修改下注记录失败 dbErr=%v", declineUid, err)
	//			tx.Rollback()
	//			_ = mtx.AbortTransaction(ctx)
	//			return nil, err
	//		}
	//	}
	//}
	//将剩余的数量分配给未被杀死的人
	if winCount > 0 {
		//求平均值
		average := utils.DecimalIntDiv(killTotal, winTotal)
		for k, v := range userData {
			if v.IsKill {
				continue
			}
			v.Reward = int64(int(utils.DecimalFloatMul(average, utils.DecimalIntByFloat(v.Num))))
			if v.Reward > 0 {
				material := new(db.WarehouseMaterial)
				_db.Model(material).Where("uid=? and type_id=?", v.UID, types.ID).First(material)
				err = tx.Model(material).Where("id=?", material.ID).Update("num", gorm.Expr("num + ?", v.Reward)).Error
				if err != nil {
					err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料失败 req=%v,dbErr=%v", v.UID, material, err)
					break
				}
				materialLog := &entity.MaterialLog{
					UID:        v.UID,
					WID:        material.ID,
					TypeID:     material.TypeID,
					TypeName:   types.Name,
					TypeImg:    types.Img,
					TypeModule: types.Module,
					LinkID:     fmt.Sprintf("%d", rounds),
					LinkTable:  "m_game_flee_room_betting_log",
					Ago:        material.Num,
					Num:        v.Reward,
					After:      material.Num + v.Reward,
					Remarks:    "游戏-七号基地-胜利 奖励",
					AddTime:    time.Now().Format(time.DateTime),
				}
				_, err = materialLogM.InsertOne(ctx, materialLog)
				if err != nil {
					err = fmt.Errorf("[Game]用户%d EndGameCard err:添加用户材料日志失败 req=%v,dbErr=%v", v.UID, materialLog, err)
					break
				}
			}
			//修改记录
			_, err = _mdb.Db.Collection("game_flee_room_betting_log").UpdateOne(ctx, bson.D{
				{"_id", v.Id},
			}, bson.M{"$set": bson.D{
				{"reward", v.Reward},
			}})
			if err != nil {
				err = fmt.Errorf("[Game]用户%d EndGameCard err:修改下注记录失败 req=%v,dbErr=%v", v.UID, v, err)
				break
			}
			userData[k] = v
		}
	}
	if err != nil {
		tx.Rollback()
		_ = mtx.AbortTransaction(ctx)
		return nil, err
	}
	_ = mtx.CommitTransaction(ctx)
	tx.Commit()
	return &userData, nil
}

func (d *GameDao) FleeMaxKillUser(ctx context.Context, rounds int64, dates string) *entity.GameFleeRoomBetting {
	bettingLog := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	findOptions := options.FindOne().SetSort(bson.M{"num": -1})
	var user entity.GameFleeRoomBetting
	err := bettingLog.FindOne(ctx, bson.D{
		{"rounds", rounds},
		{"dates", dates},
		{"isKill", true},
		{"status", 1},
	}, findOptions).Decode(&user)
	if err != nil {
		return nil
	}
	return &user
}

func (d *GameDao) GetLastFleeBetting(ctx context.Context, rounds int64) *entity.GameFleeRoomBetting {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	bettingLog := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	findOptions := options.FindOne().SetSort(bson.M{"num": -1})
	var user entity.GameFleeRoomBetting
	err := bettingLog.FindOne(ctx, bson.D{
		{"rounds", rounds},
		{"dates", dates},
		{"isKill", true},
		{"status", 1},
		{"isDecline", true},
	}, findOptions).Decode(&user)
	if err != nil {
		return nil
	}
	return &user
}

func (d *GameDao) GetFleeBetting(ctx context.Context, uid uint, rounds int64) *entity.GameFleeRoomBetting {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	bettingLog := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	findOptions := options.FindOne().SetSort(bson.M{"num": -1})
	var user entity.GameFleeRoomBetting
	err := bettingLog.FindOne(ctx, bson.D{
		{"uid", uid},
		{"rounds", rounds},
		{"dates", dates},
	}, findOptions).Decode(&user)
	if err != nil {
		return nil
	}
	return &user
}

func (d *GameDao) GameFleeLog(ctx context.Context, uid uint, req *gameFlee.PageMsg) (int64, *[]entity.GameFleeRoomBetting) {
	collection := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	whe := bson.D{
		{"uid", uid},
		{"status", 1},
	}
	count, err := collection.CountDocuments(ctx, whe)
	if err != nil {
		return 0, nil
	}
	var page, pageSize = int64(req.Page), int64(req.PageSize)
	option := options.Find()
	option.SetSort(bson.D{{"addTime", -1}}) //降序
	option.SetSkip((page - 1) * pageSize)
	option.SetLimit(pageSize)

	cur, err := collection.Find(ctx, whe, option)
	if err != nil {
		return 0, nil
	}
	var results []entity.GameFleeRoomBetting
	for cur.Next(ctx) {
		var result entity.GameFleeRoomBetting
		err = cur.Decode(&result)
		if err == mongo.ErrNoDocuments {
			return 0, nil
		}
		results = append(results, result)
	}
	return count, &results
}

func (d *GameDao) KillRoomAll(ctx context.Context, rounds int64, dates string) *[]string {
	collection := d.repo.Mongo.Db.Collection("game_flee_room_kill_log")
	whe := bson.D{
		{"rounds", rounds},
		{"killTime", dates},
	}
	cur, err := collection.Find(ctx, whe)
	if err != nil {
		return nil
	}
	var results []entity.GameFleeKillRoom
	for cur.Next(ctx) {
		var result entity.GameFleeKillRoom
		err = cur.Decode(&result)
		if err == mongo.ErrNoDocuments {
			return nil
		}
		results = append(results, result)
	}
	var roomName []string
	for _, v := range results {
		roomName = append(roomName, v.RoomName)
	}
	return &roomName
}

func (d *GameDao) FleeKillCount(ctx context.Context, id uint, minRounds, rounds int64) int64 {
	dates := utils.TimeOrDateAsYear(0, "", "Y-m-d")
	killLog := d.repo.Mongo.Db.Collection("game_flee_room_kill_log")
	count, _ := killLog.CountDocuments(ctx, bson.D{
		{"rounds", bson.M{"$gte": minRounds, "$lte": rounds}},
		{"roomID", id},
		{"killTime", dates},
	})
	return count
}

func (d *GameDao) GameCardLog(ctx context.Context, uid uint, req *game.PageMsg) (int64, *[]entity.GameCardLog) {
	collection := d.repo.Mongo.Db.Collection("game_card_log")
	whe := bson.D{
		{"uid", uid},
		{"isSkill", true},
	}
	count, err := collection.CountDocuments(ctx, whe)
	if err != nil {
		return 0, nil
	}
	var page, pageSize = int64(req.Page), int64(req.PageSize)
	option := options.Find()
	option.SetSort(bson.D{{"addTime", -1}}) //降序
	option.SetSkip((page - 1) * pageSize)
	option.SetLimit(pageSize)

	cur, err := collection.Find(ctx, whe, option)
	if err != nil {
		return 0, nil
	}
	var results []entity.GameCardLog
	for cur.Next(ctx) {
		var result entity.GameCardLog
		err = cur.Decode(&result)
		if err == mongo.ErrNoDocuments {
			return 0, nil
		}
		results = append(results, result)
	}
	return count, &results
}

func (d *GameDao) GameCardRoomCount(ctx context.Context, roomId string, dates string) int64 {
	collection := d.repo.Mongo.Db.Collection("game_card_room_log")
	count, _ := collection.CountDocuments(ctx, bson.D{
		{"roomID", roomId},
		{"dates", dates},
	})
	return count
}

func (d *GameDao) GetCardBetting(ctx context.Context, uid uint, roomId string, dates string) *entity.GameCardRoomLog {
	bettingLog := d.repo.Mongo.Db.Collection("game_card_room_log")
	var log entity.GameCardRoomLog
	err := bettingLog.FindOne(ctx, bson.D{
		{"uid", uid},
		{"roomID", roomId},
		{"dates", dates},
	}).Decode(&log)
	if err != nil {
		return nil
	}
	return &log
}

func (d *GameDao) GetMongoCardLogCount(ctx context.Context, uid uint) int64 {
	times := time.Now().AddDate(0, 0, -1)
	collection := d.repo.Mongo.Db.Collection("game_card_log")
	whe := bson.D{
		{"uid", uid},
		//{"dates", utils.TimeOrDateAsYear(0, "", "Y-m-d")},
		{"dates", utils.TimeOrDateAsYear(0, times.Format(time.DateTime), "Y-m-d")},
		{"isHangUp", false},
	}
	count, _ := collection.CountDocuments(ctx, whe)

	return count
}

func (d *GameDao) FleeRobotConf(ctx context.Context, second int) *db.GameFleeRobot {
	data := new(db.GameFleeRobot)
	d.repo.DB.Client.WithContext(ctx).Model(data).Where("second=?", second).First(data)
	return data
}

func (d *GameDao) GameFleeLogCount(ctx context.Context, uid uint, rounds int64, dates string) int64 {
	collection := d.repo.Mongo.Db.Collection("game_flee_room_betting_log")
	count, _ := collection.CountDocuments(ctx, bson.D{
		{"uid", uid},
		{"rounds", rounds},
		{"dates", dates},
	})
	return count
}

func (d *GameDao) GameCardNotEnd(ctx context.Context, uid uint) int64 {
	count, _ := d.repo.Mongo.Db.Collection("game_card_log").CountDocuments(ctx, bson.D{
		{"uid", uid},
		{"isEnd", false},
	})
	return count
}

func NewGameDao(m *repo.Manager) *GameDao {
	return &GameDao{
		repo: m,
	}
}
